package com.market.domain;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.faces.context.FacesContext;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

@Entity
@Table(name = "purchase")
public class Purchase extends BaseObject {

	/**
	 * 
	 */
	private static final long serialVersionUID = 290435196542152075L;

	public enum STATUS {
		UNKNOWN, PURCHASED, CONFIRMED, RECEIVED, PROCESSED, PAID, PAID_NOT_ARRIVED, CANCELED;
		private String getMessage(String key) {
			Locale locale = FacesContext.getCurrentInstance().getViewRoot()
					.getLocale();
			java.util.ResourceBundle resBundle = ResourceBundle.getBundle(
					"com.market.messages", locale);
			return resBundle.getString(key);
		}

		public String getLabel() {
			return this.getMessage("PURCHASE_STATUS_" + this.toString());
		}
	}

	public void purchasedToReceived() {
		for (PurchaseDetail detail : this.purchaseDetails) {
			detail.setReceivedPrice(detail.getPurchasedPrice());
			detail.setReceivedQuantity(detail.getPurchasedQuantity());
		}
	}

	@Override
	public boolean equalsId(Object o) {
		if ((o instanceof Purchase) && ((Purchase) o).getId().equals(this.id)) {
			return true;
		}
		return false;
	}

	@Transient
	public Integer getPurchasedTotalQuantity() {
		Integer total = 0;
		for (PurchaseDetail detail : this.purchaseDetails) {
			total = total + detail.getPurchasedQuantity();
		}
		return total;
	}

	@Transient
	public Double getPurchasedTotalAmount() {
		Double total = 0D;
		for (PurchaseDetail detail : this.purchaseDetails) {
			total = total + detail.getPurchasedPrice()
					* detail.getPurchasedQuantity();
		}
		return total;
	}

	@Transient
	public Double getReceivedTotalAmount() {
		Double total = 0D;
		for (PurchaseDetail detail : this.purchaseDetails) {
			total = total + detail.getReceivedPrice()
					* detail.getReceivedQuantity();
		}
		return total;
	}

	@Transient
	public Integer getReceivedTotalQuantity() {
		Integer total = 0;
		for (PurchaseDetail detail : this.purchaseDetails) {
			total = total + detail.getReceivedQuantity();
		}
		return total;
	}

	public Boolean getCanCancel() {
		if (this.status.compareTo(STATUS.RECEIVED) < 0) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}

	public Boolean getCanSave() {
		if (this.status == STATUS.UNKNOWN || this.status == STATUS.PURCHASED) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}

	public Boolean getCanConfirm() {
		if (this.status == STATUS.PURCHASED) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}

	public Boolean getCanReceive() {
		if (this.status == STATUS.CONFIRMED) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}

	public Boolean getCanProcess() {
		if (this.status == STATUS.RECEIVED) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}

	public Boolean getCanPay() {
		if (this.status == STATUS.PROCESSED) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id = 0L;
	@Column(length = 50, nullable = false, unique = true)
	private String number;
	@Column(length = 20)
	@Enumerated(EnumType.STRING)
	private STATUS status = STATUS.UNKNOWN;
	@Column(columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
	@Temporal(TemporalType.TIMESTAMP)
	private Date purchasedDate;
	@Temporal(TemporalType.TIMESTAMP)
	private Date confirmedDate;
	@Temporal(TemporalType.DATE)
	private Date requiredDate;
	@Temporal(TemporalType.TIMESTAMP)
	private Date receivedDate;
	@Temporal(TemporalType.TIMESTAMP)
	private Date processedDate;
	@Temporal(TemporalType.TIMESTAMP)
	private Date paidDate;
	@Temporal(TemporalType.TIMESTAMP)
	private Date canceledDate;
	@Column(columnDefinition = "Double default 0")
	private Double paidAmount = 0D; // How much the we have paid for this
									// purchase.
	@Column(columnDefinition = "Double default 0")
	private Double discountAmount = 0D; // How much we have been exempted for
										// this purchase
	@Column(length = 500)
	private String comments;
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "supplier_id", nullable = false)
	private Supplier supplier;
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	private List<PurchaseDetail> purchaseDetails = new ArrayList<PurchaseDetail>();

	@Override
	public String toString() {
		return "Purchase [id=" + id + ", number=" + number + ", purchasedDate="
				+ purchasedDate + ", requiredDate=" + requiredDate
				+ ", arrivedDate=" + receivedDate + ", paymentDate=" + paidDate
				+ "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((receivedDate == null) ? 0 : receivedDate.hashCode());
		result = prime * result + ((number == null) ? 0 : number.hashCode());
		result = prime * result
				+ ((paidDate == null) ? 0 : paidDate.hashCode());
		result = prime * result
				+ ((purchasedDate == null) ? 0 : purchasedDate.hashCode());
		result = prime * result
				+ ((requiredDate == null) ? 0 : requiredDate.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Purchase other = (Purchase) obj;
		if (receivedDate == null) {
			if (other.receivedDate != null)
				return false;
		} else if (!receivedDate.equals(other.receivedDate))
			return false;
		if (number == null) {
			if (other.number != null)
				return false;
		} else if (!number.equals(other.number))
			return false;
		if (paidDate == null) {
			if (other.paidDate != null)
				return false;
		} else if (!paidDate.equals(other.paidDate))
			return false;
		if (purchasedDate == null) {
			if (other.purchasedDate != null)
				return false;
		} else if (!purchasedDate.equals(other.purchasedDate))
			return false;
		if (requiredDate == null) {
			if (other.requiredDate != null)
				return false;
		} else if (!requiredDate.equals(other.requiredDate))
			return false;
		return true;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public Date getPurchasedDate() {
		return purchasedDate;
	}

	public void setPurchasedDate(Date purchasedDate) {
		this.purchasedDate = purchasedDate;
	}

	public Date getConfirmedDate() {
		return confirmedDate;
	}

	public void setConfirmedDate(Date confirmedDate) {
		this.confirmedDate = confirmedDate;
	}

	public Date getRequiredDate() {
		return requiredDate;
	}

	public void setRequiredDate(Date requiredDate) {
		this.requiredDate = requiredDate;
	}

	public Date getReceivedDate() {
		return receivedDate;
	}

	public void setReceivedDate(Date receivedDate) {
		this.receivedDate = receivedDate;
	}

	public Date getProcessedDate() {
		return processedDate;
	}

	public void setProcessedDate(Date processedDate) {
		this.processedDate = processedDate;
	}

	public Date getPaidDate() {
		return paidDate;
	}

	public void setPaidDate(Date paidDate) {
		this.paidDate = paidDate;
	}

	public Date getCanceledDate() {
		return canceledDate;
	}

	public void setCanceledDate(Date canceledDate) {
		this.canceledDate = canceledDate;
	}

	public List<PurchaseDetail> getPurchaseDetails() {
		return purchaseDetails;
	}

	public void setPurchaseDetails(List<PurchaseDetail> purchaseDetails) {
		this.purchaseDetails = purchaseDetails;
	}

	public STATUS getStatus() {
		return status;
	}

	public void setStatus(STATUS status) {
		this.status = status;
	}

	public Double getPaidAmount() {
		return paidAmount;
	}

	public void setPaidAmount(Double paidAmount) {
		this.paidAmount = paidAmount;
	}

	public Double getDiscountAmount() {
		return discountAmount;
	}

	public void setDiscountAmount(Double discountAmount) {
		this.discountAmount = discountAmount;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	public Supplier getSupplier() {
		return supplier;
	}

	public void setSupplier(Supplier supplier) {
		this.supplier = supplier;
	}

}
